// 新建一个头文件 simple_wal.h
#pragma once
#include <fstream>
#include <string>
#include <mutex>
#include <vector>
#include <functional>
#include <filesystem>
#include "common.h"

class SimpleWAL
{
public:
    SimpleWAL(const std::string &filename) : wal_filename_(filename)
    {
        open_wal_file();
    }

    ~SimpleWAL()
    {
        if (wal_file_.is_open())
        {
            wal_file_.close();
        }
    }

    // 记录页面修改到WAL
    bool LogPageUpdate(page_id_t page_id, const char *page_data, size_t data_size)
    {
        std::lock_guard<std::mutex> lock(wal_mutex_);

        if (!wal_file_.is_open())
        {
            if (!open_wal_file())
                return false;
        }

        // WAL记录格式: [操作类型][页面ID][数据大小][数据]
        char operation = 'U'; // Update操作
        wal_file_.write(&operation, sizeof(operation));
        wal_file_.write(reinterpret_cast<const char *>(&page_id), sizeof(page_id));
        wal_file_.write(reinterpret_cast<const char *>(&data_size), sizeof(data_size));
        wal_file_.write(page_data, data_size);

        wal_file_.flush(); // 确保立即写入磁盘
        return true;
    }

    // 从WAL恢复数据
    void Recover(std::function<void(page_id_t, const char *, size_t)> apply_callback)
    {
        std::lock_guard<std::mutex> lock(wal_mutex_);

        if (!std::filesystem::exists(wal_filename_))
        {
            return;
        }

        std::ifstream wal_in(wal_filename_, std::ios::binary);
        if (!wal_in)
            return;

        while (wal_in)
        {
            char operation;
            page_id_t page_id;
            size_t data_size;
            std::vector<char> buffer;

            wal_in.read(&operation, sizeof(operation));
            if (wal_in.eof())
                break;

            wal_in.read(reinterpret_cast<char *>(&page_id), sizeof(page_id));
            wal_in.read(reinterpret_cast<char *>(&data_size), sizeof(data_size));

            buffer.resize(data_size);
            wal_in.read(buffer.data(), data_size);

            if (operation == 'U')
            { // Update操作
                apply_callback(page_id, buffer.data(), data_size);
            }
        }

        // 恢复后清空WAL（检查点）
        wal_file_.close();
        // std::replace(wal_filename_.begin(), wal_filename_.end(), '/', '\\');

        // 使用 remove_all 是最安全的，因为它会递归删除非空目录
        // 但如果确定它只是一个文件，使用 remove 更精确。
        // 这里我们假设它只是一个文件，使用 remove 的安全版本：

        std::string new_filename = wal_filename_ + ".todelete";
        std::error_code ec;

        // 先删除可能存在的旧的 .todelete 文件
        std::filesystem::remove(new_filename, ec);
        ec.clear(); // 清除之前的错误码

        // 核心：重命名文件
        std::filesystem::rename(wal_filename_, new_filename, ec);

        if (ec)
        {
            std::cerr << "Error marking file for deletion (rename failed): " << ec.message() << std::endl;
            // 如果重命名失败，可以回退到直接删除，或者记录日志
        }
        else
        {
            std::cout << "File '" << wal_filename_ << "' has been marked for deletion." << std::endl;
        }
        open_wal_file();
    }

private:
    bool open_wal_file()
    {
        wal_file_.open(wal_filename_, std::ios::out | std::ios::app | std::ios::binary);
        return wal_file_.is_open();
    }

    std::string wal_filename_;
    std::ofstream wal_file_;
    std::mutex wal_mutex_;
};